package controllers

import (
	"github.com/goravel/framework/contracts/database/orm"
	"github.com/goravel/framework/contracts/http"
	"github.com/goravel/framework/facades"
	httpfacade "github.com/hulutech-web/http_result"
	"github.com/samber/lo"
	"github.com/spf13/cast"
	"goravel/app/http/requests"
	"goravel/app/models"
)

type TicketController struct {
	//Dependent services
}

func NewTicketController() *TicketController {
	return &TicketController{
		//Inject services
	}
}

func (r *TicketController) Index(ctx http.Context) http.Response {
	return nil
}

// Show ============ 1、当前工单.
// @Summary store department
// @Description 后台开单.
// @Tags TicketController
// @Security BearerAuth
// @Accept json
// @Produce json
// @Id TicketShow
// @Param Authorization header string true "Bearer token"
// @Success 200 {object} common.SuccessResponse "Successfully retrieved Menus ."
// @Failure 500 {object} common.ErrorResponse "Internal server error."
// @OperationID TicketShow
// @Router /api/admin/ticket/{id} [get]
func (r *TicketController) Show(ctx http.Context) http.Response {
	id := ctx.Request().RouteInt("id")
	ticket := models.Ticket{}
	facades.Orm().Query().Model(&models.Ticket{}).Where("id=?", id).
		With("Users").With("Parking").With("Services").With("Process").With("Kind").With("Repair").First(&ticket)
	return httpfacade.NewResult(ctx).Success("", ticket)
}

/*1创建工单*/
// Start ============ 1、后台开单,开始流转.
// @Summary store department
// @Description 后台开单.
// @Tags TicketController
// @Security BearerAuth
// @Accept json
// @Produce json
// @Id TicketStart
// @Param Authorization header string true "Bearer token"
// @Param ticketData body requests.TicketRequest true "Bearer token"
// @Success 200 {object} common.SuccessResponse "Successfully retrieved Menus ."
// @Failure 500 {object} common.ErrorResponse "Internal server error."
// @OperationID TicketStart
// @Router /api/admin/ticket/start [post]
func (r *TicketController) Start(ctx http.Context) http.Response {
	var request requests.TicketRequest
	errs, err := ctx.Request().ValidateRequest(&request)
	tx0, _ := facades.Orm().Query().Begin()
	repair := models.Repair{}
	tx0.Model(&models.Repair{}).Where("id=?", request.RepairID).First(&repair)
	if err != nil {
		return httpfacade.NewResult(ctx).Error(http.StatusInternalServerError, "数据错误", err.Error())
	}
	if errs != nil {
		return httpfacade.NewResult(ctx).ValidError("", errs.All())
	}
	user := models.User{}
	facades.Auth(ctx).User(&user)
	//1- 更新原维修单的状态
	update, err0 := tx0.Model(&models.Repair{}).Where("id=?", request.RepairID).Update("state", 1)
	if update.RowsAffected == 0 || err0 != nil {
		tx0.Rollback()
	}

	//2- 创建维修单
	ticket := models.Ticket{}
	ticket.RepairID = request.RepairID
	ticket.UserID = user.ID
	ticket.KindID = request.KindID
	ticket.TicketType = 1
	ticket.ParkingID = request.ParkingID
	ticket.RepairWay = repair.Way
	ticket.State = 1 //表示已派单

	err1 := tx0.Model(&models.Ticket{}).Create(&ticket)
	if err1 != nil {
		tx0.Rollback()
	}

	//3-关联创建,维修工
	users := []models.User{}

	err2 := tx0.Where("id in ?", request.UserIDs).Find(&users)
	err2 = tx0.Model(&ticket).Association("Users").Append(&users)
	if err2 != nil {
		tx0.Rollback()
	}

	// 4-关联创建，服务项目
	services := []models.Service{}

	err3 := tx0.Where("id in ?", request.ServiceIDs).Find(&services)
	err3 = tx0.Model(&ticket).Association("Services").Append(&services)
	if err3 != nil {
		tx0.Rollback()
	}

	// 5- 创建工单流程
	process := models.Process{}

	process.TicketID = ticket.ID
	process.RoleID = user.ID
	process.RoleName = "class_role"
	process.State = "处理中"
	process.Operation = ticket.State
	process.Comment = "已派单"
	err4 := tx0.Create(&process)
	if err4 != nil {
		tx0.Rollback()
	}
	// 6- 更新工单的当前流程id

	result, err5 := tx0.Model(&models.Ticket{}).Where("id=?", ticket.ID).Update("current_process", process.ID)
	if result.RowsAffected == 0 || err5 != nil {
		tx0.Rollback()
	}

	if err != nil {
		return httpfacade.NewResult(ctx).Error(http.StatusInternalServerError, "数据错误", err.Error())
	}
	// 3-更新流程环节
	ticket.CurrentProcess = process.ID
	tx0.Model(&ticket).Where("id=?", ticket.ID).Save(&ticket)

	//4 -工位占用
	if ticket.RepairWay == 1 {
		//判断是否被占用
		var exist bool
		tx0.Model(&models.Parking{}).Where("id=?", ticket.ParkingID).Where("state=?", "占用").Exists(&exist)
		if exist {
			tx0.Rollback()
			return httpfacade.NewResult(ctx).Error(http.StatusInternalServerError, "数据错误", "该车位已被占用")
		}
		//更新parking状态
		tx0.Model(&models.Parking{}).Where("id=?", ticket.ParkingID).Update("state", "占用")
		tx0.Model(&models.ParkingState{}).Create(&models.ParkingState{
			TicketID:  ticket.ID,
			ParkingID: ticket.ParkingID,
			State:     "占用",
		})
	}
	tx0.Commit()
	return httpfacade.NewResult(ctx).Success("开单成功", nil)
}

/*2维修工&客户签字上传照片*/
// Sign 客户维修工签字.
// @Summary store department
// @Description 待审批工单.
// @Tags TicketController
// @Security BearerAuth
// @Accept json
// @Produce json
// @Id TicketSign
// @Param Authorization header string true "Bearer token"
// @Param signData body interface{} true "签字信息"
// @Success 200 {object} common.SuccessResponse "Successfully retrieved Menus ."
// @Failure 500 {object} common.ErrorResponse "Internal server error."
// @OperationID TicketSign
// @Router /api/admin/ticket/sign [post]
func (r *TicketController) Sign(ctx http.Context) http.Response {
	//process := models.Process{}
	//需要将process向前推进，同时更新current_process
	// 1-先假定工单为正常工单，审批完成后，1）给对应的维修工分配工时，并记录工时，2）结束该工单，3）更新报修单状态

	//1- 获取当前用户的角色
	id := ctx.Request().Input("id")
	customer_sign := ctx.Request().Input("customer_sign")
	user_sign := ctx.Request().Input("user_sign")
	ticket := models.Ticket{}
	db := facades.Orm().Query()
	db.Model(&models.Ticket{}).Where("id=?", id).With("Processes", func(query orm.Query) orm.Query {
		return query.Order("id desc").Limit(1)
	}).First(&ticket)
	ticket.CustomerSign = customer_sign
	ticket.UserSign = user_sign
	var repair models.Repair
	db.Model(&models.Repair{}).Where("id=?", ticket.RepairID).First(&repair)
	if ticket.TicketType == 1 {
		//处理工单状态(正常工单)
		ticket.State = ticket.State + 1
	} else {
		ticket.State = ticket.State + 1
	}
	db.Model(&ticket).Save(&ticket)
	repair.State = ticket.State
	db.Model(&repair).Save(&repair)
	//2-流程处理
	next_process := models.Process{}
	if len(ticket.Processes) == 1 && ticket.Processes[0].ID != 0 {
		next_process.Pid = ticket.Processes[0].ID
		next_process.TicketID = ticket.ID
		next_process.RoleName = "客户签字|维修工签字"
		next_process.RoleID = ticket.UserID
		next_process.State = "处理中"
		next_process.Operation = ticket.State
		next_process.Comment = "客户签字|维修工签字"
		next_process.Images = []string{customer_sign, user_sign}
		db.Model(&models.Process{}).Create(&next_process)
	}
	// 3-更新流程环节
	ticket.CurrentProcess = next_process.ID
	db.Model(&ticket).Save(&ticket)
	return httpfacade.NewResult(ctx).Success("处理成功", nil)
}

/*3维修班长审批*/
// Pass 通过审批.
// @Summary store department
// @Description 待审批工单.
// @Tags TicketController
// @Security BearerAuth
// @Accept json
// @Produce json
// @Id TicketPass
// @Param Authorization header string true "Bearer token"
// @Param ticketData body interface{} true "工单id"
// @Success 200 {object} common.SuccessResponse "Successfully retrieved Menus ."
// @Failure 500 {object} common.ErrorResponse "Internal server error."
// @OperationID TicketPass
// @Router /api/admin/ticket/pass [post]
func (r *TicketController) Pass(ctx http.Context) http.Response {
	//1-完结
	id := ctx.Request().Input("id")
	ticket := models.Ticket{}
	user := models.User{}
	facades.Auth(ctx).User(&user)
	db := facades.Orm().Query()
	db.Model(&models.Ticket{}).Where("id=?", id).With("Processes", func(query orm.Query) orm.Query {
		return query.Order("id desc").Limit(1)
	}).With("Services").With("Kind").With("Users").Find(&ticket)
	ticket.State = ticket.State + 1

	ticket.ConfirmID = user.ID
	db.Model(&ticket).Save(&ticket)

	var repair models.Repair
	db.Model(&models.Repair{}).Where("id=?", ticket.RepairID).First(&repair)
	repair.State = ticket.State
	db.Model(&repair).Save(&repair)

	//2-1流程处理
	next_process := models.Process{}
	if len(ticket.Processes) == 1 && ticket.Processes[0].ID != 0 {
		next_process.Pid = ticket.Processes[0].ID
		next_process.TicketID = ticket.ID
		next_process.RoleName = user.Name
		next_process.Comment = "维修班长审批通过"
		next_process.RoleID = ticket.UserID
		next_process.State = "维修班班长确认"
		db.Model(&models.Process{}).Create(&next_process)
	}
	ticket.CurrentProcess = next_process.ID
	db.Model(&ticket).Save(&ticket)

	//判断当前工单是否为正常工单
	//正常工单
	if ticket.TicketType == 1 {
		//2-2工时处理
		kind_id := ticket.KindID
		service_ids := []uint{}
		for _, service := range ticket.Services {
			service_ids = append(service_ids, service.ID)
		}
		user_ids := []uint{}
		for _, u := range ticket.Users {
			user_ids = append(user_ids, u.ID)
		}
		//获取总分
		var sum float64
		db.Model(models.Manhour{}).Where("kind_id=?", kind_id).Where("service_id in ?", service_ids).Sum("score", &sum)
		averge := sum / float64(len(user_ids))
		for _, userId := range user_ids {
			db.Model(&models.Record{}).Create(&models.Record{
				RepairID: ticket.RepairID,
				TicketID: ticket.ID,
				UserID:   userId,
				Score:    averge, //平均分
			})
		}

		overTicket := models.Ticket{}
		db.Model(&models.Ticket{}).Where("id=?", id).With("Processes", func(query orm.Query) orm.Query {
			return query.Order("id desc").Limit(1)
		}).Find(&overTicket)
		overTicket.State = overTicket.State + 1
		db.Model(&overTicket).Save(&overTicket)

		over_process := models.Process{}
		if len(overTicket.Processes) == 1 && overTicket.Processes[0].ID != 0 {
			over_process.Pid = ticket.Processes[0].ID
			over_process.TicketID = ticket.ID
			over_process.RoleName = user.Name
			over_process.RoleID = ticket.UserID
			over_process.Comment = "完结"
			over_process.State = "流程完结"
			db.Model(&models.Process{}).Create(&over_process)
		}
		overTicket.CurrentProcess = over_process.ID
		db.Model(&overTicket).Save(&overTicket)

		repair.State = overTicket.State
		db.Model(&repair).Save(&repair)
		//门店维修
		if overTicket.RepairWay == 1 {
			//更新parking状态
			db.Model(&models.Parking{}).Where("id=?", overTicket.ParkingID).Update("state", "空闲")
			db.Model(&models.ParkingState{}).Create(&models.ParkingState{
				TicketID:  ticket.ID,
				ParkingID: ticket.ParkingID,
				State:     "空闲",
			})
		}
	} else {
		//异常工单
		//什么也不做
	}

	return httpfacade.NewResult(ctx).Success("处理成功", nil)
}

/*5维修作业长审批【异常工单】*/
// Confirm 通过审批.
// @Summary store department
// @Description 待审批工单.
// @Tags TicketController
// @Security BearerAuth
// @Accept json
// @Produce json
// @Id TicketConfirm
// @Param Authorization header string true "Bearer token"
// @Param ticketData body requests.TicketConfirmRequest true "工单id"
// @Success 200 {object} common.SuccessResponse "Successfully retrieved Menus ."
// @Failure 500 {object} common.ErrorResponse "Internal server error."
// @OperationID TicketConfirm
// @Router /api/admin/ticket/confirm [post]
func (r *TicketController) Confirm(ctx http.Context) http.Response {

	var confirmReqeust requests.TicketConfirmRequest
	if err := ctx.Request().Bind(&confirmReqeust); err != nil {
		return httpfacade.NewResult(ctx).Error(http.StatusInternalServerError, "参数错误", err.Error())
	}
	//1-完结
	id := confirmReqeust.Id
	ticket := models.Ticket{}
	user := models.User{}
	facades.Auth(ctx).User(&user)

	db := facades.Orm().Query()
	db.Model(&user).Where("id=?", user.ID).With("Roles").Find(&user)
	values := []string{}
	for _, role := range user.Roles {
		values = append(values, role.Value)
	}
	if !lo.Contains(values, "flow_role") {
		return httpfacade.NewResult(ctx).Error(http.StatusInternalServerError, "无权操作，非作业长", nil)
	}
	db.Model(&models.Ticket{}).Where("id=?", id).With("Processes", func(query orm.Query) orm.Query {
		return query.Order("id desc").Limit(1)
	}).With("Services").With("Kind").With("Users").Find(&ticket)
	if ticket.TicketType != 2 {
		return httpfacade.NewResult(ctx).Error(http.StatusInternalServerError, "当前工单不是异常工单", nil)
	}
	ticket.State = ticket.State + 1
	ticket.ConfirmID = user.ID
	db.Model(&ticket).Save(&ticket)
	var repair models.Repair
	db.Model(&models.Repair{}).Where("id=?", ticket.RepairID).First(&repair)
	repair.State = ticket.State
	db.Model(&repair).Save(&repair)
	//2-1流程处理
	next_process := models.Process{}
	if len(ticket.Processes) == 1 && ticket.Processes[0].ID != 0 {
		next_process.Pid = ticket.Processes[0].ID
		next_process.TicketID = ticket.ID
		next_process.RoleName = user.Name
		next_process.RoleID = ticket.UserID
		next_process.Comment = confirmReqeust.Comment
		next_process.State = "维修作业长确认"
		db.Model(&models.Process{}).Create(&next_process)
	}
	ticket.CurrentProcess = next_process.ID
	db.Model(&ticket).Save(&ticket)

	//2-2工时处理，查看是否同意

	kind_id := ticket.KindID
	service_ids := []int{}
	for _, service := range ticket.Services {
		service_ids = append(service_ids, cast.ToInt(service.ID))
	}
	user_ids := []int{}
	for _, u := range ticket.Users {
		user_ids = append(user_ids, cast.ToInt(u.ID))
	}
	//1-如果不同意，将ticket关联的service_id删除
	agree := confirmReqeust.Agree
	if !agree {
		//	1-先清空关联，2-找到剩余的关联，3-重新计算平均分
		resultArray, _ := lo.Difference(service_ids, ticket.AddServicesIds)
		//注意，这里需要从新赋值
		service_ids = resultArray
		var anySlice []any
		for _, s := range resultArray {
			anySlice = append(anySlice, s)
		}
		db.Model(&ticket).Association("Services").Clear()
		//1-重新添加服务项目
		services := []models.Service{}
		db.Model(&models.Service{}).WhereIn("id", anySlice).Find(&services)
		db.Model(&ticket).Association("Services").Append(&services)

		//1-1同时把之前的user给去掉
		resultUserArray, _ := lo.Difference(user_ids, ticket.AddUsersIds)
		//注意，这里需要从新赋值
		user_ids = resultUserArray
		var anySlice1 []any
		for _, ru := range resultUserArray {
			anySlice = append(anySlice1, ru)
		}
		//重新添加维修工
		users := []models.User{}
		db.Model(&models.User{}).WhereIn("id", anySlice1).Find(&users)
		db.Model(&ticket).Association("Users").Clear()
		db.Model(&ticket).Association("Users").Append(&users)

	}

	//获取总分
	var sum float64
	db.Model(models.Manhour{}).Where("kind_id=?", kind_id).Where("service_id in ?", service_ids).Sum("score", &sum)
	averge := sum / float64(len(user_ids))
	for _, userId := range user_ids {
		db.Model(&models.Record{}).Create(&models.Record{
			RepairID: ticket.RepairID,
			TicketID: ticket.ID,
			UserID:   cast.ToUint(userId),
			Score:    averge, //平均分
		})
	}

	overTicket := models.Ticket{}
	db.Model(&models.Ticket{}).Where("id=?", id).With("Processes", func(query orm.Query) orm.Query {
		return query.Order("id desc").Limit(1)
	}).Find(&overTicket)
	overTicket.State = overTicket.State + 1
	db.Model(&overTicket).Save(&overTicket)
	var over_repair models.Repair
	db.Model(&models.Repair{}).Where("id=?", overTicket.RepairID).First(&over_repair)
	over_repair.State = overTicket.State
	db.Model(&repair).Save(&over_repair)
	over_process := models.Process{}
	if len(overTicket.Processes) == 1 && overTicket.Processes[0].ID != 0 {
		over_process.Pid = ticket.Processes[0].ID
		over_process.TicketID = ticket.ID
		over_process.RoleName = user.Name
		over_process.RoleID = ticket.UserID
		over_process.State = "流程完结"
		db.Model(&models.Process{}).Create(&over_process)
	}
	overTicket.CurrentProcess = over_process.ID
	db.Model(&overTicket).Save(&overTicket)

	if overTicket.RepairWay == 1 {
		//更新parking状态
		db.Model(&models.Parking{}).Where("id=?", overTicket.ParkingID).Update("state", "空闲")
		db.Model(&models.ParkingState{}).Create(&models.ParkingState{
			TicketID:  overTicket.ID,
			ParkingID: ticket.ParkingID,
			State:     "空闲",
		})
	}

	return httpfacade.NewResult(ctx).Success("处理成功", nil)
}

func (r *TicketController) Update(ctx http.Context) http.Response {
	return nil
}

func (r *TicketController) Destroy(ctx http.Context) http.Response {
	return nil
}

// ToDo 待审批工单.
// @Summary store department
// @Description 待审批工单.
// @Tags TicketController
// @Security BearerAuth
// @Accept json
// @Produce json
// @Id TicketToDo
// @Param Authorization header string true "Bearer token"
// @Success 200 {object} common.SuccessResponse "Successfully retrieved Menus ."
// @Failure 500 {object} common.ErrorResponse "Internal server error."
// @OperationID TicketStart
// @Router /api/admin/ticket/todo [get]
func (r *TicketController) ToDo(ctx http.Context) http.Response {
	queries := ctx.Request().Queries()
	//1- 获取当前用户的角色
	user := models.User{}
	facades.Auth(ctx).User(&user)
	//2- 获取当前用户的所有角色
	facades.Orm().Query().Model(&user).Where("id=?", user.ID).With("Roles").Find(&user)
	values := []string{}
	for _, role := range user.Roles {
		values = append(values, role.Value)
	}
	db := facades.Orm().Query()
	if lo.Contains(values, "flow_role") {
		//只看异常工单
		tickets := []models.Ticket{}

		res, err := httpfacade.NewResult(ctx).SearchByParams(queries, map[string]interface{}{}).
			ResultPagination(&tickets, "Processes", "Kind", "Process", "Users", "Services", "Repair", "Repair.Car")
		if err != nil {
			return httpfacade.NewResult(ctx).Error(http.StatusInternalServerError, err.Error(), nil)
		}
		return res
	}

	if lo.Contains(values, "class_role") && !lo.Contains(values, "flow_role") {
		//只看正常工单
		tickets := []models.Ticket{}
		res, err := httpfacade.NewResult(ctx).SearchByParams(queries, map[string]interface{}{}).
			ResultPagination(&tickets, "Processes", "Kind", "Process", "Users", "Services", "Repair", "Repair.Car")
		if err != nil {
			return httpfacade.NewResult(ctx).Error(http.StatusInternalServerError, err.Error(), nil)
		}
		return res
	}

	if lo.Contains(values, "employee_role") && !lo.Contains(values, "class_role") && !lo.Contains(values, "flow_role") {
		//维修工，只看自己的
		//只看正常工单
		type MyTicket struct {
			TicketID uint `json:"ticket_id" form:"ticket_id"`
		}
		myTickets := []MyTicket{}
		db.Raw("select ticket_id from ticket_user where user_id = ?", user.ID).Scan(&myTickets)
		ticketIDs := []any{}
		for _, ticket := range myTickets {
			ticketIDs = append(ticketIDs, any(ticket.TicketID))
		}
		tickets := []models.Ticket{}
		res, err := httpfacade.NewResult(ctx).SearchByIncludes("id", ticketIDs).
			SearchByParams(queries, map[string]interface{}{"ticket_type": 1}, []string{"ticket_type"}...).
			ResultPagination(&tickets, "Processes", "Process", "Users", "Kind", "Services", "Repair", "Repair.Car")
		if err != nil {
			return httpfacade.NewResult(ctx).Error(http.StatusInternalServerError, err.Error(), nil)
		}
		return res
	}
	return httpfacade.NewResult(ctx).Error(http.StatusInternalServerError, "身份异常", nil)
}

// AbToDo 待审批异常工单.
// @Summary store department
// @Description 待审批工单.
// @Tags TicketController
// @Security BearerAuth
// @Accept json
// @Produce json
// @Id TicketAbToDo
// @Param Authorization header string true "Bearer token"
// @Success 200 {object} common.SuccessResponse "Successfully retrieved Menus ."
// @Failure 500 {object} common.ErrorResponse "Internal server error."
// @OperationID TicketStart
// @Router /api/admin/ticket/abtodo [get]
func (r *TicketController) AbToDo(ctx http.Context) http.Response {
	queries := ctx.Request().Queries()
	//1- 获取当前用户的角色
	user := models.User{}
	facades.Auth(ctx).User(&user)
	//2- 获取当前用户的所有角色
	facades.Orm().Query().Model(&user).Where("id=?", user.ID).With("Roles").Find(&user)
	values := []string{}
	for _, role := range user.Roles {
		values = append(values, role.Value)
	}
	db := facades.Orm().Query()
	if lo.Contains(values, "flow_role") {
		//只看异常工单
		tickets := []models.Ticket{}

		res, err := httpfacade.NewResult(ctx).SearchByParams(queries, map[string]interface{}{}).
			ResultPagination(&tickets, "Processes", "Kind", "Process", "Users", "Services", "Repair", "Repair.Car")
		if err != nil {
			return httpfacade.NewResult(ctx).Error(http.StatusInternalServerError, err.Error(), nil)
		}
		return res
	}

	if lo.Contains(values, "class_role") && !lo.Contains(values, "flow_role") {
		//只看正常工单
		tickets := []models.Ticket{}
		res, err := httpfacade.NewResult(ctx).SearchByParams(queries, map[string]interface{}{}).
			ResultPagination(&tickets, "Processes", "Kind", "Process", "Users", "Services", "Repair", "Repair.Car")
		if err != nil {
			return httpfacade.NewResult(ctx).Error(http.StatusInternalServerError, err.Error(), nil)
		}
		return res
	}

	if lo.Contains(values, "employee_role") && !lo.Contains(values, "class_role") && !lo.Contains(values, "flow_role") {
		//维修工，只看自己的
		//只看正常工单
		type MyTicket struct {
			TicketID uint `json:"ticket_id" form:"ticket_id"`
		}
		myTickets := []MyTicket{}
		db.Raw("select ticket_id from ticket_user where user_id = ?", user.ID).Scan(&myTickets)
		ticketIDs := []any{}
		for _, ticket := range myTickets {
			ticketIDs = append(ticketIDs, any(ticket.TicketID))
		}
		tickets := []models.Ticket{}
		res, err := httpfacade.NewResult(ctx).SearchByIncludes("id", ticketIDs).
			SearchByParams(queries, map[string]interface{}{"ticket_type": 1}, []string{"ticket_type"}...).
			ResultPagination(&tickets, "Processes", "Process", "Users", "Kind", "Services", "Repair", "Repair.Car")
		if err != nil {
			return httpfacade.NewResult(ctx).Error(http.StatusInternalServerError, err.Error(), nil)
		}
		return res
	}
	return httpfacade.NewResult(ctx).Error(http.StatusInternalServerError, "身份异常", nil)
}

// AbNormal 改变为 异常工单.
// @Summary store department
// @Description 待审批工单.
// @Tags TicketController
// @Security BearerAuth
// @Accept json
// @Produce json
// @Id TicketAbNormal
// @Param Authorization header string true "Bearer token"
// @Param ticketData body interface{} true "异常工单数据"
// @Success 200 {object} common.SuccessResponse "Successfully retrieved Menus ."
// @Failure 500 {object} common.ErrorResponse "Internal server error."
// @OperationID TicketAbNormal
// @Router /api/admin/ticket/abnormal [post]
func (r *TicketController) AbNormal(ctx http.Context) http.Response {
	var abNormalRequest requests.AbNormalRequest
	errors, err := ctx.Request().ValidateRequest(&abNormalRequest)

	//非手工时
	if abNormalRequest.Hand == "1" {
		if err != nil {
			return httpfacade.NewResult(ctx).Error(http.StatusInternalServerError, "数据错误", err.Error())
		}
		if errors != nil {
			return httpfacade.NewResult(ctx).ValidError("", errors.All())
		}
		id := abNormalRequest.ID
		ticket := models.Ticket{}
		db := facades.Orm().Query()
		db.Where("id = ?", id).First(&ticket)
		services_ids := abNormalRequest.ServiceIDS
		users_ids := abNormalRequest.UserIDS

		ticket.TicketType = 2
		ticket.AddServicesIds = services_ids
		ticket.AddUsersIds = users_ids
		db.Model(&models.Ticket{}).Where("id=?", id).Save(&ticket)
		// 4-关联创建，服务项目
		services := []models.Service{}

		db.Where("id in ?", services_ids).Find(&services)
		db.Model(&ticket).Association("Services").Append(&services)

		// 4-关联维修工
		users := []models.User{}
		db.Where("id in ?", users_ids).Find(&users)

		db.Model(&ticket).Association("Users").Append(&users)
		return httpfacade.NewResult(ctx).Success("修改成功", nil)
	} else {
		id := abNormalRequest.ID
		ticket := models.Ticket{}
		db := facades.Orm().Query()
		db.Where("id = ?", id).First(&ticket)
		services_ids := abNormalRequest.ServiceIDS
		users_ids := abNormalRequest.UserIDS

		ticket.TicketType = 2
		ticket.AddServicesIds = services_ids
		ticket.AddUsersIds = users_ids
		ticket.HandScoreIds = abNormalRequest.ScoreAssigns
		db.Model(&models.Ticket{}).Where("id=?", id).Save(&ticket)
		// 4-关联创建，服务项目
		services := []models.Service{}

		db.Where("id in ?", services_ids).Find(&services)
		//
		db.Model(&ticket).Association("Services").Append(&services)

		// 4-关联维修工
		users := []models.User{}
		db.Where("id in ?", users_ids).Find(&users)

		db.Model(&ticket).Association("Users").Append(&users)
		return httpfacade.NewResult(ctx).Success("修改成功", nil)
	}
}

// AbNormalDetail 异常工单详情.
// @Summary store department
// @Description 待审批工单.
// @Tags TicketController
// @Security BearerAuth
// @Accept json
// @Produce json
// @Id TicketAbNormalDetail
// @Param Authorization header string true "Bearer token"
// @Param ticketData body interface{} true "异常工单数据"
// @Success 200 {object} common.SuccessResponse "Successfully retrieved Menus ."
// @Failure 500 {object} common.ErrorResponse "Internal server error."
// @OperationID TicketAbNormalDetail
// @Router /api/admin/ticket/{id}/abnormaldetail [get]
func (r *TicketController) AbNormalDetail(ctx http.Context) http.Response {
	id := ctx.Request().RouteInt("id")
	ticket := models.Ticket{}
	facades.Orm().Query().Where("id = ?", id).First(&ticket)
	if ticket.TicketType != 2 {
		return httpfacade.NewResult(ctx).Error(http.StatusInternalServerError, "不是异常工单", nil)
	}
	newTicket := models.Ticket{}
	facades.Orm().Query().Model(&models.Ticket{}).Where("id = ?", id).
		With("Services").With("Processes").With("Kind").With("Process").With("Users").With("Repair").Find(&newTicket)
	return httpfacade.NewResult(ctx).Success("", newTicket)
}

/*2维修工&客户签字上传照片*/
func (r *TicketController) MiniSign(ctx http.Context) http.Response {
	//process := models.Process{}
	//需要将process向前推进，同时更新current_process
	// 1-先假定工单为正常工单，审批完成后，1）给对应的维修工分配工时，并记录工时，2）结束该工单，3）更新报修单状态

	//1- 获取当前用户的角色
	id := ctx.Request().Input("id")
	customer_sign := ctx.Request().Input("customer_sign")
	user_sign := ctx.Request().Input("user_sign")
	ticket := models.Ticket{}
	db := facades.Orm().Query()
	db.Model(&models.Ticket{}).Where("id=?", id).With("Processes", func(query orm.Query) orm.Query {
		return query.Order("id desc").Limit(1)
	}).First(&ticket)
	ticket.CustomerSign = customer_sign
	ticket.UserSign = user_sign
	var repair models.Repair
	db.Model(&models.Repair{}).Where("id=?", ticket.RepairID).First(&repair)
	if ticket.TicketType == 1 {
		//处理工单状态(正常工单)
		ticket.State = ticket.State + 1
	} else {
		ticket.State = ticket.State + 1
	}
	db.Model(&ticket).Save(&ticket)
	repair.State = ticket.State
	db.Model(&repair).Save(&repair)

	//2-流程处理
	next_process := models.Process{}
	if len(ticket.Processes) == 1 && ticket.Processes[0].ID != 0 {
		next_process.Pid = ticket.Processes[0].ID
		next_process.TicketID = ticket.ID
		next_process.RoleName = "客户签字|维修工签字"
		next_process.RoleID = ticket.UserID
		next_process.State = "处理中"
		next_process.Operation = ticket.State
		next_process.Comment = "客户签字|维修工签字"
		next_process.Images = []string{customer_sign, user_sign}
		db.Model(&models.Process{}).Create(&next_process)
	}
	// 3-更新流程环节
	ticket.CurrentProcess = next_process.ID
	db.Model(&ticket).Save(&ticket)
	return httpfacade.NewResult(ctx).Success("处理成功", nil)
}

func (r *TicketController) MiniShow(ctx http.Context) http.Response {
	id := ctx.Request().RouteInt("id")
	ticket := models.Ticket{}
	facades.Orm().Query().Model(&models.Ticket{}).Where("id=?", id).
		With("Users").With("Parking").With("ParkingStates").With("Services").
		With("Process").With("Records").With("Processes").With("Kind").With("Repair").First(&ticket)
	return httpfacade.NewResult(ctx).Success("", ticket)
}

func (r *TicketController) MiniPass(ctx http.Context) http.Response {
	//1-完结
	id := ctx.Request().Input("id")
	ticket := models.Ticket{}
	user := models.User{}
	facades.Auth(ctx).User(&user)
	db := facades.Orm().Query()
	db.Model(&models.Ticket{}).Where("id=?", id).With("Processes", func(query orm.Query) orm.Query {
		return query.Order("id desc").Limit(1)
	}).With("Services").With("Kind").With("Users").Find(&ticket)
	ticket.State = ticket.State + 1

	ticket.ConfirmID = user.ID
	db.Model(&ticket).Save(&ticket)

	var repair models.Repair
	db.Model(&models.Repair{}).Where("id=?", ticket.RepairID).First(&repair)
	repair.State = ticket.State
	db.Model(&repair).Save(&repair)

	//2-1流程处理
	next_process := models.Process{}
	if len(ticket.Processes) == 1 && ticket.Processes[0].ID != 0 {
		next_process.Pid = ticket.Processes[0].ID
		next_process.TicketID = ticket.ID
		next_process.RoleName = user.Name
		next_process.Comment = "维修班长审批通过"
		next_process.RoleID = ticket.UserID
		next_process.State = "维修班班长确认"
		db.Model(&models.Process{}).Create(&next_process)
	}
	ticket.CurrentProcess = next_process.ID
	db.Model(&ticket).Save(&ticket)

	//判断当前工单是否为正常工单
	//正常工单
	if ticket.TicketType == 1 {
		//2-2工时处理
		kind_id := ticket.KindID
		service_ids := []uint{}
		for _, service := range ticket.Services {
			service_ids = append(service_ids, service.ID)
		}
		user_ids := []uint{}
		for _, u := range ticket.Users {
			user_ids = append(user_ids, u.ID)
		}
		//获取总分
		var sum float64
		db.Model(models.Manhour{}).Where("kind_id=?", kind_id).Where("service_id in ?", service_ids).Sum("score", &sum)
		averge := sum / float64(len(user_ids))
		for _, userId := range user_ids {
			db.Model(&models.Record{}).Create(&models.Record{
				RepairID: ticket.RepairID,
				TicketID: ticket.ID,
				UserID:   userId,
				Score:    averge, //平均分
			})
		}

		overTicket := models.Ticket{}
		db.Model(&models.Ticket{}).Where("id=?", id).With("Processes", func(query orm.Query) orm.Query {
			return query.Order("id desc").Limit(1)
		}).Find(&overTicket)
		overTicket.State = overTicket.State + 1
		db.Model(&overTicket).Save(&overTicket)

		over_process := models.Process{}
		if len(overTicket.Processes) == 1 && overTicket.Processes[0].ID != 0 {
			over_process.Pid = ticket.Processes[0].ID
			over_process.TicketID = ticket.ID
			over_process.RoleName = user.Name
			over_process.RoleID = ticket.UserID
			over_process.Comment = "完结"
			over_process.State = "流程完结"
			db.Model(&models.Process{}).Create(&over_process)
		}
		overTicket.CurrentProcess = over_process.ID
		db.Model(&overTicket).Save(&overTicket)

		repair.State = overTicket.State
		db.Model(&repair).Save(&repair)
		//门店维修
		if overTicket.RepairWay == 1 {
			//更新parking状态
			db.Model(&models.Parking{}).Where("id=?", overTicket.ParkingID).Update("state", "空闲")
			db.Model(&models.ParkingState{}).Create(&models.ParkingState{
				TicketID:  ticket.ID,
				ParkingID: ticket.ParkingID,
				State:     "空闲",
			})
		}
	} else {
		//异常工单
		//什么也不做
	}

	return httpfacade.NewResult(ctx).Success("处理成功", nil)
}

func (r *TicketController) MiniStart(ctx http.Context) http.Response {
	var request requests.TicketRequest
	errs, err := ctx.Request().ValidateRequest(&request)
	tx0, _ := facades.Orm().Query().Begin()
	repair := models.Repair{}
	tx0.Model(&models.Repair{}).Where("id=?", request.RepairID).First(&repair)
	if err != nil {
		return httpfacade.NewResult(ctx).Error(http.StatusInternalServerError, "数据错误", err.Error())
	}
	if errs != nil {
		return httpfacade.NewResult(ctx).ValidError("", errs.All())
	}
	user := models.User{}
	facades.Auth(ctx).User(&user)

	//1- 更新原维修单的状态
	update, err0 := tx0.Model(&models.Repair{}).Where("id=?", request.RepairID).Update("state", 1)
	if update.RowsAffected == 0 || err0 != nil {
		tx0.Rollback()
	}
	tx0.Commit()

	//2- 创建维修单
	ticket := models.Ticket{}
	tx1, _ := facades.Orm().Query().Begin()
	ticket.RepairID = request.RepairID
	ticket.UserID = user.ID
	ticket.KindID = request.KindID
	ticket.RepairWay = repair.Way
	ticket.TicketType = 1
	ticket.ParkingID = request.ParkingID
	ticket.State = 1 //表示已派单

	err1 := tx1.Model(&models.Ticket{}).Create(&ticket)
	if err1 != nil {
		tx1.Rollback()
	}
	tx1.Commit()

	//3-关联创建,维修工
	users := []models.User{}
	tx2, _ := facades.Orm().Query().Begin()

	err2 := tx2.Where("id in ?", request.UserIDs).Find(&users)
	err2 = tx2.Model(&ticket).Association("Users").Append(&users)
	if err2 != nil {
		tx1.Rollback()
	}
	tx2.Commit()

	// 4-关联创建，服务项目
	services := []models.Service{}
	tx3, _ := facades.Orm().Query().Begin()

	err3 := tx3.Where("id in ?", request.ServiceIDs).Find(&services)
	err3 = tx3.Model(&ticket).Association("Services").Append(&services)
	if err3 != nil {
		tx1.Rollback()
	}
	tx3.Commit()

	// 5- 创建工单流程
	process := models.Process{}
	tx4, _ := facades.Orm().Query().Begin()

	process.TicketID = ticket.ID
	process.RoleID = user.ID
	process.RoleName = "class_role"
	process.State = "处理中"
	process.Operation = ticket.State
	process.Comment = "已派单"
	err4 := tx4.Create(&process)
	if err4 != nil {
		tx4.Rollback()
	}
	tx4.Commit()

	// 6- 更新工单的当前流程id
	tx5, _ := facades.Orm().Query().Begin()

	result, err5 := tx5.Model(&models.Ticket{}).Where("id=?", ticket.ID).Update("current_process", process.ID)
	if result.RowsAffected == 0 || err5 != nil {
		tx5.Rollback()
	}
	tx5.Commit()

	if err != nil {
		return httpfacade.NewResult(ctx).Error(http.StatusInternalServerError, "数据错误", err.Error())
	}
	// 3-更新流程环节
	ticket.CurrentProcess = process.ID
	facades.Orm().Query().Model(&ticket).Where("id=?", ticket.ID).Save(&ticket)

	//4 -工位占用
	if ticket.RepairWay == 1 {
		//判断是否被占用
		var exist bool
		facades.Orm().Query().Model(&models.Parking{}).Where("id=?", ticket.ParkingID).Where("state=?", "占用").Exists(&exist)
		if exist {
			return httpfacade.NewResult(ctx).Error(http.StatusInternalServerError, "数据错误", "该车位已被占用")
		}
		//更新parking状态
		facades.Orm().Query().Model(&models.Parking{}).Where("id=?", ticket.ParkingID).Update("state", "占用")
		facades.Orm().Query().Model(&models.ParkingState{}).Create(&models.ParkingState{
			TicketID:  ticket.ID,
			ParkingID: ticket.ParkingID,
			State:     "占用",
		})
	}

	return httpfacade.NewResult(ctx).Success("开单成功", nil)
}

// 小程序改异常单
func (r *TicketController) MiniAbNormal(ctx http.Context) http.Response {

	var miniabNormalRequest requests.MiniAbNormalRequest
	errors, err := ctx.Request().ValidateRequest(&miniabNormalRequest)
	if err != nil {
		return httpfacade.NewResult(ctx).Error(http.StatusInternalServerError, "数据错误", err.Error())
	}
	if errors != nil {
		return httpfacade.NewResult(ctx).ValidError("", errors.All())
	}
	//非手工时
	if miniabNormalRequest.Hand == "1" {
		id := miniabNormalRequest.ID
		ticket := models.Ticket{}
		db := facades.Orm().Query()
		db.Where("id = ?", id).First(&ticket)
		services_ids := miniabNormalRequest.ServiceIDS
		users_ids := miniabNormalRequest.UserIDS

		ticket.TicketType = 2
		ticket.AddServicesIds = services_ids
		ticket.AddUsersIds = users_ids
		db.Model(&models.Ticket{}).Where("id=?", id).Save(&ticket)
		// 4-关联创建，服务项目
		services := []models.Service{}

		db.Where("id in ?", services_ids).Find(&services)
		db.Model(&ticket).Association("Services").Append(&services)

		// 4-关联维修工
		users := []models.User{}
		db.Where("id in ?", users_ids).Find(&users)

		db.Model(&ticket).Association("Users").Append(&users)
		return httpfacade.NewResult(ctx).Success("修改成功", nil)
	} else {
		id := miniabNormalRequest.ID
		ticket := models.Ticket{}
		db := facades.Orm().Query()
		db.Where("id = ?", id).First(&ticket)
		services_ids := miniabNormalRequest.ServiceIDS
		users_ids := miniabNormalRequest.UserIDS

		ticket.TicketType = 2
		ticket.AddServicesIds = services_ids
		ticket.AddUsersIds = users_ids
		ticket.HandScoreIds = miniabNormalRequest.ScoreAssigns
		db.Model(&models.Ticket{}).Where("id=?", id).Save(&ticket)
		// 4-关联创建，服务项目
		services := []models.Service{}

		db.Where("id in ?", services_ids).Find(&services)
		//
		db.Model(&ticket).Association("Services").Append(&services)

		// 4-关联维修工
		users := []models.User{}
		db.Where("id in ?", users_ids).Find(&users)

		db.Model(&ticket).Association("Users").Append(&users)
		return httpfacade.NewResult(ctx).Success("修改成功", nil)
	}
}

func (r *TicketController) MiniConfirm(ctx http.Context) http.Response {

	var confirmReqeust requests.TicketConfirmRequest
	if err := ctx.Request().Bind(&confirmReqeust); err != nil {
		return httpfacade.NewResult(ctx).Error(http.StatusInternalServerError, "参数错误", err.Error())
	}
	//1-完结
	id := confirmReqeust.Id
	ticket := models.Ticket{}
	user := models.User{}
	facades.Auth(ctx).User(&user)

	db := facades.Orm().Query()
	db.Model(&user).Where("id=?", user.ID).With("Roles").Find(&user)
	values := []string{}
	for _, role := range user.Roles {
		values = append(values, role.Value)
	}
	if !lo.Contains(values, "flow_role") {
		return httpfacade.NewResult(ctx).Error(http.StatusInternalServerError, "无权操作，非作业长", nil)
	}
	db.Model(&models.Ticket{}).Where("id=?", id).With("Processes", func(query orm.Query) orm.Query {
		return query.Order("id desc").Limit(1)
	}).With("Services").With("Kind").With("Users").Find(&ticket)
	if ticket.TicketType != 2 {
		return httpfacade.NewResult(ctx).Error(http.StatusInternalServerError, "当前工单不是异常工单", nil)
	}
	ticket.State = ticket.State + 1
	ticket.ConfirmID = user.ID
	db.Model(&ticket).Save(&ticket)
	var repair models.Repair
	db.Model(&models.Repair{}).Where("id=?", ticket.RepairID).First(&repair)
	repair.State = ticket.State
	db.Model(&repair).Save(&repair)
	//2-1流程处理
	next_process := models.Process{}
	if len(ticket.Processes) == 1 && ticket.Processes[0].ID != 0 {
		next_process.Pid = ticket.Processes[0].ID
		next_process.TicketID = ticket.ID
		next_process.RoleName = user.Name
		next_process.RoleID = ticket.UserID
		next_process.Comment = confirmReqeust.Comment
		next_process.State = "维修作业长确认"
		db.Model(&models.Process{}).Create(&next_process)
	}
	ticket.CurrentProcess = next_process.ID
	db.Model(&ticket).Save(&ticket)

	//2-2工时处理，查看是否同意

	kind_id := ticket.KindID
	service_ids := []int{}
	for _, service := range ticket.Services {
		service_ids = append(service_ids, cast.ToInt(service.ID))
	}
	user_ids := []int{}
	for _, u := range ticket.Users {
		user_ids = append(user_ids, cast.ToInt(u.ID))
	}
	//1-如果不同意，将ticket关联的service_id删除
	agree := confirmReqeust.Agree
	if !agree {
		//	1-先清空关联，2-找到剩余的关联，3-重新计算平均分
		resultArray, _ := lo.Difference(service_ids, ticket.AddServicesIds)
		//注意，这里需要从新赋值
		service_ids = resultArray
		var anySlice []any
		for _, s := range resultArray {
			anySlice = append(anySlice, s)
		}
		db.Model(&ticket).Association("Services").Clear()
		//1-重新添加服务项目
		services := []models.Service{}
		db.Model(&models.Service{}).WhereIn("id", anySlice).Find(&services)
		db.Model(&ticket).Association("Services").Append(&services)

		//1-1同时把之前的user给去掉
		resultUserArray, _ := lo.Difference(user_ids, ticket.AddUsersIds)
		//注意，这里需要从新赋值
		user_ids = resultUserArray
		var anySliceUsers []any
		for _, ru := range resultUserArray {
			anySliceUsers = append(anySliceUsers, ru)
		}
		//重新添加维修工
		users := []models.User{}
		db.Model(&models.User{}).WhereIn("id", anySliceUsers).Find(&users)
		db.Model(&ticket).Association("Users").Clear()
		db.Model(&ticket).Association("Users").Append(&users)

		//获取总分
		//判断ticket对应的handScore中有没有数据，如果有数据，直接读取handScore内的内容，如果没有内容
		var sum float64
		db.Model(models.Manhour{}).Where("kind_id=?", kind_id).Where("service_id in ?", service_ids).Sum("score", &sum)
		averge := sum / float64(len(user_ids))
		for _, userId := range user_ids {
			db.Model(&models.Record{}).Create(&models.Record{
				RepairID: ticket.RepairID,
				TicketID: ticket.ID,
				UserID:   cast.ToUint(userId),
				Score:    averge, //平均分
			})
		}

		overTicket := models.Ticket{}
		db.Model(&models.Ticket{}).Where("id=?", id).With("Processes", func(query orm.Query) orm.Query {
			return query.Order("id desc").Limit(1)
		}).Find(&overTicket)
		overTicket.State = overTicket.State + 1
		db.Model(&overTicket).Save(&overTicket)
		var over_repair models.Repair
		db.Model(&models.Repair{}).Where("id=?", overTicket.RepairID).First(&over_repair)
		over_repair.State = overTicket.State
		db.Model(&repair).Save(&over_repair)
		over_process := models.Process{}
		if len(overTicket.Processes) == 1 && overTicket.Processes[0].ID != 0 {
			over_process.Pid = ticket.Processes[0].ID
			over_process.TicketID = ticket.ID
			over_process.RoleName = user.Name
			over_process.RoleID = ticket.UserID
			over_process.State = "流程完结"
			over_process.Comment = "流程完结"
			db.Model(&models.Process{}).Create(&over_process)
		}
		overTicket.CurrentProcess = over_process.ID
		db.Model(&overTicket).Save(&overTicket)

		if overTicket.RepairWay == 1 {
			//更新parking状态
			db.Model(&models.Parking{}).Where("id=?", overTicket.ParkingID).Update("state", "空闲")
			db.Model(&models.ParkingState{}).Create(&models.ParkingState{
				TicketID:  overTicket.ID,
				ParkingID: ticket.ParkingID,
				State:     "空闲",
			})
		}
	} else {
		//同意
		//以下是手工逻辑
		for _, scoreitem := range ticket.HandScoreIds {
			db.Model(&models.Record{}).Create(&models.Record{
				RepairID: ticket.RepairID,
				TicketID: ticket.ID,
				UserID:   cast.ToUint(scoreitem.UserID),
				Score:    scoreitem.Score, //平均分
			})
		}
		overTicket := models.Ticket{}
		db.Model(&models.Ticket{}).Where("id=?", id).With("Processes", func(query orm.Query) orm.Query {
			return query.Order("id desc").Limit(1)
		}).Find(&overTicket)
		overTicket.State = overTicket.State + 1
		db.Model(&overTicket).Save(&overTicket)
		var over_repair models.Repair
		db.Model(&models.Repair{}).Where("id=?", overTicket.RepairID).First(&over_repair)
		over_repair.State = overTicket.State
		db.Model(&repair).Save(&over_repair)
		over_process := models.Process{}
		if len(overTicket.Processes) == 1 && overTicket.Processes[0].ID != 0 {
			over_process.Pid = ticket.Processes[0].ID
			over_process.TicketID = ticket.ID
			over_process.RoleName = user.Name
			over_process.RoleID = ticket.UserID
			over_process.State = "流程完结"
			over_process.Comment = "流程完结"
			db.Model(&models.Process{}).Create(&over_process)
		}
		overTicket.CurrentProcess = over_process.ID
		db.Model(&overTicket).Save(&overTicket)

		if overTicket.RepairWay == 1 {
			//更新parking状态
			db.Model(&models.Parking{}).Where("id=?", overTicket.ParkingID).Update("state", "空闲")
			db.Model(&models.ParkingState{}).Create(&models.ParkingState{
				TicketID:  overTicket.ID,
				ParkingID: ticket.ParkingID,
				State:     "空闲",
			})
		}
	}

	return httpfacade.NewResult(ctx).Success("处理成功", nil)
}
